package cn.ywang.pattern.template;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Jdbc模版类
 *
 * @author BeatificWang
 * @date 2019/3/18 7:18
 */
public class JdbcTemplate {

	private DataSource dataSource;

	public JdbcTemplate(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public List<?> executeQuery(String sql, Object[] values, RowMapper<?> mapper) {
		List<?> result = null;
		try {
			// 1. 获取连接
			Connection connection = this.getConnection();
			// 2. 新建语句集
			PreparedStatement ps = this.createPreparedStatement(connection, sql);
			// 3. 查询并保存至结果集
			ResultSet rs = this.getResultSet(ps, values);
			// 4. 处理结果集
			result = this.processResultSet(rs, mapper);
			// 5. 关闭结果集
			this.closeResultSet(rs);
			// 6. 关闭语句集
			this.closePreparedStatement(ps);
			// 7. 关闭连接
			this.closeConnection(connection);
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	private void closeConnection(Connection connection) throws SQLException {
		connection.close();
	}

	private void closePreparedStatement(PreparedStatement ps) throws SQLException {
		ps.close();
	}

	private void closeResultSet(ResultSet rs) throws SQLException {
		rs.close();
	}

	private List<?> processResultSet(ResultSet rs, RowMapper<?> mapper) throws SQLException {
		List<Object> result = new ArrayList<>(2);
		int rowNum = 1;
		while (rs.next()) {
			result.add(mapper.mapRow(rs, rowNum++));
		}
		return result;
	}

	private ResultSet getResultSet(PreparedStatement ps, Object[] values) throws SQLException {
		int i = 0;
		for (Object object : values) {
			ps.setObject(i++, object);
		}
		return ps.executeQuery();
	}

	private PreparedStatement createPreparedStatement(Connection connection, String sql) throws SQLException {
		return connection.prepareStatement(sql);
	}

	private Connection getConnection() throws SQLException {
		return this.dataSource.getConnection();
	}


}

